﻿using SL651Center2.x.Enums;
using System.Text;
using System.Text.RegularExpressions;
using TouchSocket.Core;

namespace SL651Center2.x.Messages
{
    /// <summary>
    /// 均匀时段报
    /// </summary>
    public class MessageTime : IMessage
    {
        /// <summary>
        /// 流水号
        /// </summary>
        public byte[] SerialNumber { get; set; } = Array.Empty<byte>();
        /// <summary>
        /// 流水号数字形式
        /// </summary>
        public ushort SerialNum { get; set; }
        /// <summary>
        /// 发报时间
        /// </summary>
        public byte[] SendTime { get; set; } = Array.Empty<byte>();
        /// <summary>
        /// 发报时间字符串形式
        /// </summary>
        public string SendTimeStr { get; set; } = string.Empty;
        /// <summary>
        /// 遥测站地址
        /// </summary>
        public byte[] TelemetryAddress { get; set; } = Array.Empty<byte>();
        /// <summary>
        /// 遥测站地址的字符串形式
        /// </summary>
        public string TelemetryAddress_str { get; set; } = string.Empty;
        /// <summary>
        /// 遥测站分类码
        /// </summary>
        public TelemetryStationCode TelemetryStation { get; set; }
        /// <summary>
        /// 观测时间
        /// </summary>
        public byte[] ObservationTime { get; set; } = Array.Empty<byte>();
        /// <summary>
        /// 观测时间字符串
        /// </summary>
        public string ObservationTimeStr { get; set; } = string.Empty;
        /// <summary>
        /// 时间步长码
        /// </summary>
        public byte[] TimeStepCode { get; set; } = Array.Empty<byte>();
        /// <summary>
        /// 时间步长码字符串
        /// </summary>
        public string TimeStepCodeStr { get; set; } = string.Empty;

        /// <summary>
        /// 时段数据
        /// </summary>
        public TimeData[] TimeDatas { get; set; } = Array.Empty<TimeData>();

        public void Read(in ByteBlock byteBlock)
        {
            //流水号
            SerialNumber = byteBlock.ReadToSpan(2).ToArray();
            SerialNum = Convert.ToUInt16(Helper.ToHEXString(SerialNumber), 16);

            //发报时间
            SendTime = byteBlock.ReadToSpan(6).ToArray();
            SendTimeStr = Helper.ByteToBCDTime(SendTime);

            //遥测站地址
            var code = byteBlock.ReadByte();
            byteBlock.ReadByte();
            TelemetryAddress = byteBlock.ReadToSpan(5).ToArray();
            TelemetryAddress_str = Helper.ToHEXString(TelemetryAddress);

            //遥测站分类码
            TelemetryStation = (TelemetryStationCode)byteBlock.ReadByte();

            //观测时间
            var tt = byteBlock.ReadByte();
            byteBlock.Seek(1, SeekOrigin.Current);
            ObservationTime = byteBlock.ReadToSpan(5).ToArray();
            ObservationTimeStr = Helper.ByteToBCDTime(ObservationTime);

            //时间步长码
            var drCode = byteBlock.ReadByte();
            //跳过数据定义
            byteBlock.Seek(1, SeekOrigin.Current);
            TimeStepCode = byteBlock.ReadToSpan(3).ToArray();
            TimeStepCodeStr = Helper.ByteToBCDTime(TimeStepCode);


            //读取一个标识符
            var elemCode = byteBlock.ReadByte();
            //读取数据定义
            var dlen = byteBlock.ReadByte();
            var dalen = dlen >> 3;
            var dalen1 = dlen & 0x07;

            var (d, pre) = ElementInfo.GetValueType((ElementCode)elemCode);
            var (name, unit) = ElementInfo.Instance.GetInfo((ElementCode)elemCode);

            string regex = "^[Ff]*$";

            List<TimeData> datas = new List<TimeData>();
            List<decimal> decimals = new List<decimal>();


            while (byteBlock.Position != byteBlock.Length - 3)
            {
                var va = new byte[d];
                byteBlock.Read(va);
                var d1 = Helper.ToHEXString(va);
                int num1;
                if (elemCode >= 0xF4 && elemCode <= 0xFC)
                {
                    num1 = Convert.ToUInt16(d1, 16);
                }
                else
                {
                    num1 = Helper.HEXToBCDInt(d1);
                }
                decimal value;
                if (Regex.IsMatch(d1, regex))
                {
                    value = 0;
                }
                else if (pre != 0)
                {
                    value = num1 / pre;
                }
                else
                {
                    value = Convert.ToDecimal(num1);
                }
                decimals.Add(value);

            }
            TimeData timeData = new TimeData()
            {
                Code = (ElementCode)elemCode,
                Name = name,
                Unit = unit,
                Value = decimals.ToArray(),
            };
            datas.Add(timeData);
            TimeDatas = datas.ToArray();

        }

        public void ReadASCII(in ByteBlock byteBlock)
        {
            //流水号
            SerialNumber = byteBlock.ReadToSpan(4).ToArray();
            SerialNum = Convert.ToUInt16(SerialNumber.ToASCIIString(), 16);

            //发报时间
            SendTime = byteBlock.ReadToSpan(12).ToArray();
            SendTimeStr = Helper.StringToBCDTime(SendTime.ToASCIIString());

            var datab = byteBlock.ToArray(byteBlock.Position);
            var datastr = datab.ToASCIIString();
            var arr = datastr.Split(" ");

            //遥测站地址
            TelemetryAddress_str = arr[1];
            TelemetryAddress = Encoding.ASCII.GetBytes(TelemetryAddress_str);

            //遥测站分类码
            var typestr = arr[2];
            if (Enum.IsDefined(typeof(TelemetryStationCode), typestr))
            {
                var typecode = (TelemetryStationCode)Enum.Parse(typeof(TelemetryStationCode), typestr);
                TelemetryStation = typecode;
            }

            //观测时间
            var tt = arr[4];
            ObservationTime = Encoding.ASCII.GetBytes(tt);
            ObservationTimeStr = Helper.StringToBCDTime(tt);

            //时间步长码
            var drCode = arr[5];
            string drStr = string.Empty;
            if (drCode.StartsWith("DRD"))
            {
                drStr = $"时间步长码：{drCode[^2..]}d00h00min";
            }
            else if (drCode.StartsWith("DRH"))
            {
                drStr = $"时间步长码：00d{drCode[^2..]}h00min";
            }
            else if (drCode.StartsWith("DRN"))
            {
                drStr = $"时间步长码：00d00h{drCode[^2..]}min";
            }
            TimeStepCode = Encoding.ASCII.GetBytes(drCode);
            TimeStepCodeStr = drStr;

            List<TimeData> datas = new List<TimeData>();

            for (int i = 6; i < arr.Length - 1; i++)
            {
                var elemCode = arr[i];
                if (elemCode == "DRP")
                {
                    var elementCode = (ElementCode)Enum.Parse(typeof(ElementCode), elemCode);
                    var (name, unit) = ElementInfo.Instance.GetInfo(elemCode);

                    decimal[] values = new decimal[12];
                    for (int j = 0; j < 12; j++)
                    {
                        var d1 = arr[i + 1];
                        var v = Convert.ToDecimal(Convert.ToUInt16(d1, 16)) / 10;
                        if (Regex.IsMatch(d1, "^[Ff]*$"))
                        {
                            v = 0;
                        }
                        values[j] = v;

                        i += 1;
                    }
                    TimeData timeData = new TimeData()
                    {
                        Code = elementCode,
                        Name = name,
                        Unit = unit,
                        Value = values,
                    };
                    datas.Add(timeData);

                    continue;
                }

                if (elemCode.StartsWith("DRZ"))
                {
                    var elementCode = (ElementCode)Enum.Parse(typeof(ElementCode), elemCode);
                    var (name, unit) = ElementInfo.Instance.GetInfo(elemCode);

                    decimal[] values = new decimal[12];
                    for (int j = 0; j < 12; j++)
                    {
                        var d1 = arr[i + 1];
                        var v = Convert.ToDecimal(Convert.ToUInt16(d1, 16)) / 100;
                        if (Regex.IsMatch(d1, "^[Ff]*$"))
                        {
                            v = 0;
                        }
                        values[j] = v;

                        i += 1;
                    }
                    TimeData timeData = new TimeData()
                    {
                        Code = elementCode,
                        Name = name,
                        Unit = unit,
                        Value = values,
                    };
                    datas.Add(timeData);
                    continue;
                }

                if (Enum.IsDefined(typeof(ElementCode), elemCode))
                {
                    var elementCode = (ElementCode)Enum.Parse(typeof(ElementCode), elemCode);
                    (string name, string unit) = ElementInfo.Instance.GetInfo(elementCode);

                    List<decimal> values = new List<decimal>();
                    do
                    {
                        var d1 = arr[++i];
                        var v = Convert.ToDecimal(d1);
                        values.Add(v);
                    } while (!Enum.IsDefined(typeof(ElementCode), arr[i + 1]) && i + 1 != arr.Length - 1);


                    TimeData data = new TimeData()
                    {
                        Code = elementCode,
                        Name = name,
                        Unit = unit,
                        Value = values.ToArray(),
                    };
                    datas.Add(data);

                }

                TimeDatas = datas.ToArray();

            }


        }
    }
}
